package com.suxin.classloader;

import lombok.Data;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;

/**
 * @author Tang
 * @classname MyClassLoader
 * @description [  ]
 * @date 2021/7/16 11:00
 */
@Data
public class MyClassLoader extends ClassLoader {

    private String path;

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String className = name.substring(name.lastIndexOf(".") + 1);
        byte[] cls = getData(className);
        return defineClass(name, cls, 0, cls.length);
    }

    private byte[] getData(String className) {
        try {
            Optional<Path> firstClass = Files.find(Paths.get(path), 1, (path, basic) -> {
                return path.getFileName().toString().endsWith(className + ".class");
            }, FileVisitOption.FOLLOW_LINKS).findFirst();
            return firstClass.map(path -> {
                try (ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(1024)) {
                    Files.copy(path, byteOutputStream);
                    return byteOutputStream.toByteArray();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                throw new RuntimeException("not found class!");
            }).get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    public static void main(String[] args) throws Exception {
        MyClassLoader myClassLoader = new MyClassLoader();
        myClassLoader.setPath("G:\\suxin");
        Class<?> aClass = myClassLoader.loadClass("com.suxin.classloader.entity.StudentService");
        System.out.println(aClass.hashCode());
        System.out.println(aClass.getClassLoader());
        Object newInstance = aClass.newInstance();
        aClass.getMethod("test", null)
                .invoke(newInstance, null);


        MyClassLoader myClassLoader1 = new MyClassLoader();
        myClassLoader1.setPath("G:\\suxin");
        Class<?> aClass1 = myClassLoader1.loadClass("com.suxin.classloader.entity.StudentService");
        System.out.println(aClass1.hashCode());
    }

    @Override
    public String toString() {
        return "MyClassLoader{}...";
    }
}